﻿#include "GUIFESensorDialog.h"
#include "ui_GUIFESensorDialog.h"

#include "FITK_Kernel/FITKCore/FITKActionOperator.h"
#include "FITK_Kernel/FITKAppFramework/FITKAppFramework.h"
#include "FITK_Kernel/FITKAppFramework/FITKGlobalData.h"
#include "FITK_Kernel/FITKCore/FITKDataRepo.h"
#include "FITK_Kernel/FITKCore/FITKVec3DAlg.h"

#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsFEModel.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsSensors.h"
#include "FITK_Component/FITKAcousticsModel/FITKAcousticsDiscNodeList.h"
#include "FITK_Component/FITKAcousticsModel/FITKAbstractFESubSys.h"

#include "FITK_Interface/FITKInterfaceModel/FITKAbstractElement.h"

#include "PickDataProvider/PickedDataProvider.h"
#include "PickDataProvider/PickedData.h"
#include "OperatorsInterface/GraphEventOperator.h"

#include <QMessageBox>

namespace GUI {
    GUIFESensorDialog::GUIFESensorDialog(Core::FITKActionOperator* oper, QWidget* parent/* = nullptr*/) :
        GUIDialogBase(parent),
        _oper(oper),
        _ui(new Ui::GUIFESensorDialog)
    {
        _ui->setupUi(this);
        // 设置对话框关闭时自动删除
        setAttribute(Qt::WA_DeleteOnClose);
        //去掉问号
        Qt::WindowFlags flags = windowFlags();
        flags &= ~Qt::WindowContextHelpButtonHint;
        setWindowFlags(flags);
        //初始化界面
        this->initImage();
        this->initWidgetHideComponent();
        //创建新的传感器数据
        this->createNewSensorData();
        //初始化数据
        this->initData();
    }

    GUIFESensorDialog::GUIFESensorDialog(Acoustics::FITKAcousticsSensors* obj, Core::FITKActionOperator* oper, QWidget* parent /*= nullptr*/) :
        GUIDialogBase(parent),
        _obj(obj),
        _oper(oper),
        _ui(new Ui::GUIFESensorDialog)
    {
        _ui->setupUi(this);
        // 设置对话框关闭时自动删除
        setAttribute(Qt::WA_DeleteOnClose);
        //去掉问号
        Qt::WindowFlags flags = windowFlags();
        flags &= ~Qt::WindowContextHelpButtonHint;
        setWindowFlags(flags);
        //初始化界面
        this->initImage();
        this->initWidgetHideComponent();
        //初始化数据
        this->initData();
    }

    GUIFESensorDialog::~GUIFESensorDialog()
    {
        //释放数据
        if (_ui) {
            delete _ui;
            _ui = nullptr;
        }
    }

    void GUIFESensorDialog::initData()
    {
        //初始化参数
        if (!_obj || !_oper) return;
        //获取数据
        QString name = _obj->getDataObjectName();
        if (name.isEmpty())
        {
            name = "Sensor-1";
            name = this->ckeckNameFromMgr(name);
        }
        QString feObjName{};
        Acoustics::FITKAbstractFESubSys* feSubSys = _obj->getFESubSysObj();
        if (feSubSys) feObjName = feSubSys->getDataObjectName();
        QPair<int, int> nodeElemID = _obj->getConnection();
        Acoustics::FITKAcousticsSensors::SensorConnectionType connectType = _obj->getConnectionType();
        Acoustics::FITKAcousticsSensors::SensorResultType resultType = _obj->getSensorResultType();
        double orientation[3] = { 0,0,0 };
        _obj->getGlobalOrientation(orientation);
        //初始化界面数据
        this->initResultTypeComboBox(connectType);
        //设置界面数据
        _ui->lineEdit_Name->setText(name);
        _ui->lineEdit_FESubSys->setText(feObjName);
        _ui->radioButton_Node->setChecked(true);
        _ui->lineEdit_Node->setText(QString::number(nodeElemID.first));
        _ui->lineEdit_Element->setText(QString::number(nodeElemID.second));
        _ui->radioButton_Global->setChecked(true);
        int index = _ui->comboBox_Type->findData(int(resultType));
        _ui->comboBox_Type->setCurrentIndex(index);
        _ui->lineEdit_Gx->setText(QString::number(orientation[0]));
        _ui->lineEdit_Gy->setText(QString::number(orientation[1]));
        _ui->lineEdit_Gz->setText(QString::number(orientation[2]));
    }

    void GUIFESensorDialog::on_pushButton_Cancel_clicked()
    {
        //点击取消按键动作
        this->reject();
    }

    void GUIFESensorDialog::on_pushButton_OK_clicked()
    {
        if (!_oper)return;
        //获取操作器动作类型
        QString operType;
        _oper->argValue<QString>("OperModelType", operType);
        if (operType.isEmpty())
        {
            delete _obj;
            this->reject();
            return;
        }
        //创建动作
        if (operType == "Create")
        {
            if (!this->createObjData())
                return;
        }
        //修改动作
        else if (operType == "Edit")
        {
            if (!this->editObjData())
                return;
        }
        this->accept();
    }

    void GUIFESensorDialog::on_radioButton_Node_toggled(bool checkState)
    {
        Q_UNUSED(checkState);
        //点类型动作
        _ui->lineEdit_Node->setEnabled(true);
        _ui->lineEdit_Element->setEnabled(false);
        this->initResultTypeComboBox(Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionNode);
    }

    void GUIFESensorDialog::on_radioButton_Element_toggled(bool checkState)
    {
        Q_UNUSED(checkState);
        //单元类型动作
        _ui->lineEdit_Element->setEnabled(true);
        _ui->lineEdit_Node->setEnabled(false);
        this->initResultTypeComboBox(Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionElement);
    }

    void GUIFESensorDialog::on_radioButton_Global_toggled(bool checkState)
    {
        Q_UNUSED(checkState);
        //全局坐标动作
        _ui->lineEdit_Gx->setEnabled(true);
        _ui->lineEdit_Gy->setEnabled(true);
        _ui->lineEdit_Gz->setEnabled(true);
        _ui->lineEdit_Lx->setEnabled(false);
        _ui->lineEdit_Ly->setEnabled(false);
        _ui->lineEdit_Lz->setEnabled(false);
    }

    void GUIFESensorDialog::on_radioButton_Local_toggled(bool checkState)
    {
        Q_UNUSED(checkState);
        //局部坐标动作
        _ui->lineEdit_Lx->setEnabled(true);
        _ui->lineEdit_Ly->setEnabled(true);
        _ui->lineEdit_Lz->setEnabled(true);
        _ui->lineEdit_Gx->setEnabled(false);
        _ui->lineEdit_Gy->setEnabled(false);
        _ui->lineEdit_Gz->setEnabled(false);
    }

    void GUIFESensorDialog::on_lineEdit_Gx_editingFinished()
    {
        //更新局部方向
        this->updateLocalOrientation();
    }

    void GUIFESensorDialog::on_lineEdit_Gy_editingFinished()
    {
        //更新局部方向
        this->updateLocalOrientation();
    }

    void GUIFESensorDialog::on_lineEdit_Gz_editingFinished()
    {
        //更新局部方向
        this->updateLocalOrientation();
    }

    void GUIFESensorDialog::on_lineEdit_Lx_editingFinished()
    {
        //更新全局方向
        this->updateGlobalOrientation();
    }

    void GUIFESensorDialog::on_lineEdit_Ly_editingFinished()
    {
        //更新全局方向
        this->updateGlobalOrientation();
    }

    void GUIFESensorDialog::on_lineEdit_Lz_editingFinished()
    {
        //更新全局方向
        this->updateGlobalOrientation();
    }

    void GUIFESensorDialog::initWidgetHideComponent()
    {
        //初始化界面隐藏组件
        _ui->radioButton_Element->setVisible(false);
        _ui->lineEdit_Element->setVisible(false);
        _ui->label_Component->setVisible(false);
        _ui->comboBox_Component->setVisible(false);
        _ui->label_Location->setVisible(false);
        _ui->comboBox_Location->setVisible(false);
        _ui->radioButton_Local->setVisible(false);
        _ui->lineEdit_Lx->setVisible(false);
        _ui->label_Lx->setVisible(false);
        _ui->lineEdit_Ly->setVisible(false);
        _ui->label_Ly->setVisible(false);
        _ui->lineEdit_Lz->setVisible(false);
        _ui->label_Lz->setVisible(false);
    }

    void GUIFESensorDialog::initResultTypeComboBox(int type)
    {
        _ui->comboBox_Type->clear();
        //获取子系统类型
        Acoustics::FITKAbstractFESubSys::FESubSysType feType = Acoustics::FITKAbstractFESubSys::FESubSysType::FENone;
        Acoustics::FITKAbstractFESubSys* model = _obj->getFESubSysObj();
        if (model) feType = model->getFESubSysType();
        //通过类型初始化界面
        if (type == Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionNode && feType == Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure)
        {
            _ui->comboBox_Type->addItem(tr("Velocity [magnitude]"), int(Acoustics::FITKAcousticsSensors::SensorResultType::SensorResultVelocityMagnitude));
            _ui->comboBox_Type->addItem(tr("Velocity [directional]"), int(Acoustics::FITKAcousticsSensors::SensorResultType::SensorResultVelocityDirectional));
        }
        else if (type == Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionNode && feType == Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic)
        {
            _ui->comboBox_Type->addItem(tr("Pressure"), int(Acoustics::FITKAcousticsSensors::SensorResultType::SensorResultPressure));
        }
        else if (type == Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionElement)
        {

        }
    }

    void GUIFESensorDialog::initImage()
    {
        //初始化图标
        _ui->label_Image->setPixmap(QPixmap(":/ToolBar/toolBar/FE_transducer.png"));
    }

    void GUIFESensorDialog::createNewSensorData()
    {
        if (!_oper) return;
        int pickDataObjID = -1, elementID = -1;
        if (!_oper->argValue<int>("pickDataObjID", pickDataObjID) || !_oper->argValue<int>("ElementID", elementID)) return;
        //获取节点和单元数据
        Acoustics::FITKAcousticsDiscModel* discModel = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (discModel == nullptr && discModel->getFEModel() == nullptr)return;
        Acoustics::FITKAcousticsDiscNodeList* nodeList = discModel->getNodes();
        Acoustics::FITKAcousticsFESubSysElementList* elementList = discModel->getFEModel()->getFESubSysElementList();
        if (!nodeList || !elementList) return;
        //获取单元
        Interface::FITKAbstractElement* element = elementList->getElementByID(elementID);
        if (!element) return;
        int nodeID = element->getNodeID(0);
        int dim = element->getElementDim();
        //计算方向
        double globalOrientation[3] = { 0,0,0 };
        if (dim == 1)
        {
            globalOrientation[0] = 0.0;
            globalOrientation[1] = 0.0;
            globalOrientation[2] = 1.0;
        }
        else if (dim == 2)
        {
            if (element->getNodeCount() < 3) return;
            Core::FITKNode* node1 = nodeList->getNodeByID(nodeID);
            Core::FITKNode* node2 = nodeList->getNodeByID(element->getNodeID(1));
            Core::FITKNode* node3 = nodeList->getNodeByID(element->getNodeID(2));
            if (!node1 || !node2 || !node3) return;
            Core::FITKPoint a = Core::Subtract(*node1, *node2);
            Core::FITKPoint b = Core::Subtract(*node1, *node3);
            Core::FITKPoint orien = Core::CrossProduct(a, b);
            globalOrientation[0] = orien[0];
            globalOrientation[1] = orien[1];
            globalOrientation[2] = orien[2];
        }
        else
            return;
        _obj = new Acoustics::FITKAcousticsSensors;
        _obj->setConnection(nodeID, elementID);
        _obj->setFESubSysObjID(pickDataObjID);
        _obj->setGlobalOrientation(globalOrientation);
        Acoustics::FITKAbstractFESubSys* model = _obj->getFESubSysObj();
        if (!model) return;
        Acoustics::FITKAbstractFESubSys::FESubSysType feType = model->getFESubSysType();
        if (feType == Acoustics::FITKAbstractFESubSys::FESubSysType::FEStructure)
            _obj->setSensorResultType(Acoustics::FITKAcousticsSensors::SensorResultType::SensorResultVelocityMagnitude);
        else if (feType == Acoustics::FITKAbstractFESubSys::FESubSysType::FEAcoustic)
            _obj->setSensorResultType(Acoustics::FITKAcousticsSensors::SensorResultType::SensorResultPressure);
    }

    QString GUIFESensorDialog::ckeckNameFromMgr(QString name)
    {
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discMgr = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discMgr) return name;
        //获取FE子系统管理器
        Acoustics::FITKAcousticsFEModel* feModel = discMgr->getFEModel();
        if (!feModel) return name;
        Acoustics::FITKAcousticsSensorsManager* sensorMgr = feModel->getSensorManager();
        if (!sensorMgr) return name;
        return sensorMgr->checkName(name);
    }

    void GUIFESensorDialog::updateGlobalOrientation()
    {

    }

    void GUIFESensorDialog::updateLocalOrientation()
    {

    }

    bool GUIFESensorDialog::createObjData()
    {
        if (!_oper || !_obj) return false;
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discMgr = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discMgr) return false;
        //获取FE子系统管理器
        Acoustics::FITKAcousticsFEModel* feModel = discMgr->getFEModel();
        if (!feModel) return false;
        Acoustics::FITKAcousticsSensorsManager* sensorMgr = feModel->getSensorManager();
        if (!sensorMgr) return false;

        //获取板名称-查重处理
        QString name = _ui->lineEdit_Name->text();
        if (sensorMgr->getDataByName(name)) {
            QMessageBox::warning(this, "", tr("\"%1\" already exists and cannot be overwritten.").arg(name), QMessageBox::Ok);
            return false;
        }
        //设置名称
        _obj->setDataObjectName(name);
        //设置界面数据
        this->getDataFormWidget();
        //设置数据
        sensorMgr->appendDataObj(_obj);
        _oper->setArgs("objID", _obj->getDataObjectID());

        //清除拾取模式和高亮
        GUI::GUIPickInfo::ClearPickInfo();
        return true;
    }

    bool GUIFESensorDialog::editObjData()
    {
        if (!_oper || !_obj) return false;
        //获取离散数据
        Acoustics::FITKAcousticsDiscModel* discMgr = FITKAPP->getGlobalData()->getMeshData<Acoustics::FITKAcousticsDiscModel>();
        if (!discMgr) return false;
        //获取FE子系统管理器
        Acoustics::FITKAcousticsFEModel* feModel = discMgr->getFEModel();
        if (!feModel) return false;
        Acoustics::FITKAcousticsSensorsManager* sensorMgr = feModel->getSensorManager();
        if (!sensorMgr) return false;

        //获取板名称-查重处理
        QString name = _ui->lineEdit_Name->text();
        //名称重复判断
        if (name != _obj->getDataObjectName())
            if (sensorMgr->getDataByName(name)) {
                QMessageBox::warning(this, "", tr("\"%1\" already exists and cannot be overwritten.").arg(name), QMessageBox::Ok);
                return false;
            }
        //设置名称
        _obj->setDataObjectName(name);
        //设置界面数据
        this->getDataFormWidget();
        _oper->setArgs("objID", _obj->getDataObjectID());
        return true;
    }

    void GUIFESensorDialog::accept()
    {
        disHight();
        GUIDialogBase::accept();
    }

    void GUIFESensorDialog::reject()
    {
        //清除拾取模式和高亮
        GUI::GUIPickInfo::ClearPickInfo();
        //关闭窗口
        _oper->setArgs("objID", -1);
        QString operModel;
        if (_oper->argValue("OperModelType", operModel) && operModel == "Create")
        {
            delete _obj;
            _obj = nullptr;
        }

        disHight();
        GUIDialogBase::reject();
    }

    void GUIFESensorDialog::getDataFormWidget()
    {
        //从界面中获取数据
        double orientation[3] = { 0,0,0 };
        Acoustics::FITKAcousticsSensors::SensorConnectionType connectType = Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionNode;
        if (_ui->radioButton_Element->isCheckable()) connectType = Acoustics::FITKAcousticsSensors::SensorConnectionType::SensorConnectionElement;
        int resultType = _ui->comboBox_Type->currentData().toInt();
        orientation[0] = _ui->lineEdit_Gx->text().toDouble();
        orientation[1] = _ui->lineEdit_Gy->text().toDouble();
        orientation[2] = _ui->lineEdit_Gz->text().toDouble();
        //设置数据
        if (!_obj) return;
        _obj->setConnectionType(connectType);
        _obj->setSensorResultType((Acoustics::FITKAcousticsSensors::SensorResultType)resultType);
        _obj->setGlobalOrientation(orientation);
    }
    void GUIFESensorDialog::showEvent(QShowEvent * event)
    {
        if (_obj) {
            hightGraphObj(_obj->getDataObjectID());
        }
        GUIDialogBase::showEvent(event);

    }
    void GUIFESensorDialog::disHight()
    {
        if (_obj) {
            disHightGraphObj(_obj->getDataObjectID());
        }
    }
}
